<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>

<body>

</body>
<script>

    /* es6 的类的写法
        1. 对象属性
        2. 对象方法
        */
    class Person {

        constructor(name, age) {
            /* this.属性名称 = 初始化的值，值可以是外部传递，也可以是自己手工写死 */
            this.username = name;
            this.age = age;
            // 自己写死的属性 一般自己写死的属性代表是私有属性，外部不要访问（约定俗成）
            this._salary = 2000;

        }

        say() {
            console.log(`${this.username} say hello`);
        }
        /* 在构造函数里面和 class 里面写方法都是实例对象的方法和属性 */

        /* 如果我们想在类的本身上面增加属性和方法，该如何处理？
            如果是类的属性我们称之为静态属性；
            如果是方法我们称之为静态方法 
        */
        static getInfo() {
            console.log('静态方法');
        }
        static type = 'yellow human';

    }

    /* 
    Person 父类
    Man 子类

        注意：在javascript里面只能做单继承，一个类只能存在一个父类
    */
    /* 面试题：在javascript里面是否支持多继承，如果支持，写一个示例，如果不支持是否有替代访问可以达到多继承的效果？ */
    class Man extends Person {
        // 有的时候，我们的 子类也需要有一些属性和方法，该如何处理？
        constructor(name, age, height, weight) {
            /* 如果我们继承的父类存在构造函数，则必须显示的使用 super 关键字调用
            一下父类的构造函数（super 关键 等价父类的 constructor ） */
            super(name, age);
            /* 
            super(name, age);

            Must call super constructor in derived class before accessing 'this' or returning from derived constructor
            如果不写 super 关键字，则会报错
            */


            /* super 必须写在 当前类的 constructor 第一行  */
            this.height = height;
            this.weight = weight;

            /* 如果写在属性的初始化下面，也是会报错的
             Uncaught ReferenceError: Must call super constructor in derived class before accessing 'this' or returning from derived constructor
                 super(name, age);

            */
            // super(name, age);
        }

        work() {
            console.log(`my name is ${this.username}, i can work`);
        }

        /* 子类把父类的方法覆盖（在子类里面写了一个和父类同名的方法，称之为 重写），到达多态的效果
            1. 封装
            2. 继承
            3. 多态（重写）
            
        */
        say() {
            console.log(`${this.username} 子类的 say 方法被执行了！`);
        }


    }
    const p1 = new Person('mark', 23);
    p1.say(); // mark say hello

    const m1 = new Man('张晓明', 24, 175, 70);
    m1.say(); //


</script>

</html>